/*********************\
* Author:Dzlua
* QQ:505544956
* Time:2017/04/08
\**********************/
#ifndef __LUA_HELPER_H__
#define __LUA_HELPER_H__

#include <LuaPlus.h>
using namespace LuaPlus;
#include <spdui/spdui.h>

namespace DuiLib {

#define SDLUA_NEWCOBJ "__NewCObj__"

class LuaClassBase
{
public:
    virtual void  Release() { delete this; }
    virtual void* GetCObj() { return m_cobj; }
    virtual void  SetCObj(void* data) { m_cobj = data; }
protected:
    void* m_cobj;
};

#define SDLUA_CLASS_DECLARE(classname) \
    public:\
        static void Register(LuaState *L);\
        static void UnRegister(LuaState *L);\
        static classname* GetInterface(void* data) {\
            if (!data) return 0;\
            LuaClassBase* newclass = new classname;\
            newclass->SetCObj(data);\
        }\
    public:\
        classname() {}\
        virtual ~##classname() {}

#define SDLUA_BEGIN_REGISTER_BASE(classname, name) \
    void classname::Register(LuaState *L) {\
        LuaObject obj = LuaHelperNS::AddToMetas(L, #name);\
        obj.SetObject("__index", obj);\
        obj.RegisterDirect(SDLUA_NEWCOBJ, &classname::GetInterface);
#define SDLUA_BEGIN_REGISTER(classname, name, parent) \
    void classname::Register(LuaState *L) {\
        LuaObject obj = LuaHelperNS::AddToMetas(L, #name, #parent);\
        obj.SetObject("__index", obj);\
        obj.RegisterDirect(SDLUA_NEWCOBJ, &classname::GetInterface);

#define SDLUA_END_REGISTER }

#define SDLUA_BEGIN_UNREGISTER(classname, name) \
    void classname::UnRegister(LuaState *L) {

#define SDLUA_END_UNREGISTER(name) \
        LuaHelperNS::RemoveFromMetas(L, #name);\
    }

#define SDLUA_REGISTER_FUN_CPP(classname, name, fun) \
    obj.RegisterObjectDirect(#name, (classname*)0, &classname::fun);
#define SDLUA_REGISTER_FUN_LUA(classname, name, fun) \
    obj.RegisterObjectFunctor(#name, &classname::fun);

#define LuaHelperNS DuiLib::LuaHelper
namespace LuaHelper{

void Register(LuaState *L);
void UnRegister(LuaState *L);

//get the table where saved Luaclass metatables
LuaObject GetTableOfMetas(LuaState *L);
//create a table to saved Luaclass metatables.return the table.
LuaObject AddToMetas(LuaState *L, const char* key, const char* parent = 0);
//get the table from saved Luaclass metatables
LuaObject GetFromMetas(LuaState *L, const char* key);
//remove the table from saved Luaclass metatables
void RemoveFromMetas(LuaState *L, const char* key);

//get the table where saved Luaclass objects
LuaObject GetTableOfObjs(LuaState *L);
//create a table to saved Luaclass objects.return the table.
LuaObject AddToObjs(LuaState *L, void* data);
//get the table from saved Luaclass objects
LuaObject GetFromObjs(LuaState *L, void* data);
//remove the table from saved Luaclass objects
void RemoveFromObjs(LuaState *L, void* data);

//add a event to Objs
bool SetEventToObjs(LuaState *L, void* key, const char* evtname, LuaObject event);
//get a event from Objs
LuaObject GetEventFromObjs(LuaState *L, void* key, const char* eventname);
//remove the event from Objs
void RemoveEventFromObjs(LuaState *L, void* key, const char* eventname);

//set a c++ pointer to table.
void SetCObject(LuaObject obj, LuaClassBase* cobj);
//get the c++ pointer if had.
LuaClassBase* GetCObject(LuaObject obj);
//get the c++ pointer's data
void* GetCObjectData(LuaObject obj);

SDTString GetTString(LuaObject obj, SDTString defvalue = _T(""));
SDTChar GetTChar(LuaObject obj, TCHAR defvalue = _T('\0'));
DWORD GetDWord(LuaObject obj, DWORD defvalue = 0);
int GetInt(LuaObject obj, int defvalue = 0);
UINT GetUInt(LuaObject obj, UINT defvalue = 0);
LONG GetLong(LuaObject obj, LONG defvalue = 0);
bool GetBool(LuaObject obj, bool defvalue = false);
LPVOID GetLPVoid(LuaObject obj, LPVOID defvalue = 0);
RECT GetRect(LuaObject obj, int defvalue = 0);
POINT GetPoint(LuaObject obj, int defvalue = 0);
SIZE GetSize(LuaObject obj, int defvalue = 0);
int GetRollTextDirect(LuaObject obj, int defvalue = 0);
SYSTEMTIME GetSysTime(LuaObject obj);

void PushCObj(LuaState *L, void* data);
void PushTString(LuaState *L, SDTString str);
void PushTChar(LuaState *L, SDTChar str);
void PushLPVoid(LuaState *L, LPVOID data);
void PushRect(LuaState *L, RECT &rc);
void PushPoint(LuaState *L, POINT &pt);
void PushSize(LuaState *L, SIZE &sz);
void PushSysTime(LuaState *L, SYSTEMTIME &st);


}
}

#endif //__LUA_HELPER_H__